#! /usr/local/bin/python3
#versionV1.6
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from PIL import ImageGrab
from PIL import Image
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from openpyxl import load_workbook
from glob import glob
from email.mime.base import MIMEBase
from email import encoders
from Txzhandan import TxZhandan
import datetime
import zipfile
import smtplib
import random
import ddddocr
import time
import os as os
import shutil as shutil
import hmac
import hashlib
import base64
import urllib.parse
import requests
import json
import sys
#import virtkey
# os.environ['DISPLAY'] = ':0'
# import pyautogui as ui
#全局变量
today = datetime.date.today() # 1. 获取「今天」
last_month = today.replace(month=today.month - 1) # 2.获取前一个月
lastmoth = last_month.strftime('%Y-%m')
# v = virtkey.virtkey()

#定义一个压缩打包函数
def zipDir(dirpath, outFullName):
    # '''
    # 压缩指定文件夹
    # :param dirpath: 目标文件夹路径
    # :param outFullName:  压缩文件保存路径+XXXX.zip
    # :return: 无
    # '''
    zip = zipfile.ZipFile(outFullName, 'w', zipfile.ZIP_DEFLATED)
    for path, dirnames, filenames in os.walk(dirpath):
        #去掉目标和路径，只对目标文件夹下边的文件及文件夹进行压缩（包括父文件夹本身）
        this_path = os.path.abspath('.')
        fpath = path.replace(this_path, '')
        for filename in filenames:
            zip.write(os.path.join(path, filename), os.path.join(fpath, filename))
    zip.close()
   
#定义一个移动文件函数
def mymovefile(srcfile,dstpath):                       # 移动函数
    if not os.path.isfile(srcfile):
        print ("%s not exist!"%(srcfile))
    else:
        fpath,fname=os.path.split(srcfile)             # 分离文件名和路径
        if not os.path.exists(dstpath):
            os.makedirs(dstpath)                       # 创建路径
        shutil.move(srcfile, dstpath + fname)          # 移动文件
        print("move %s -> %s" % (srcfile, dstpath + fname))

#定义识别验证码是否通过函数
def CodePass(type:str) -> int:
    if 'pdf' in type:
        try:
            time.sleep(3)
            driver.find_element(by=By.XPATH, value='/html/body/div[6]/div[2]/div[2]/button[2]/span').click()
            DingText('%s的PDF验证码识别错误，重试中' % (type))
            return 0
        except:
            return 1
    elif 'xls' in type:
            try:
                time.sleep(3)
                driver.find_element(by=By.XPATH, value='/html/body/div[6]/div[2]/div[2]/button[2]/span').click()
                DingText('%s的xls验证码识别错误，重视中' % (name))
                return 0
            except:
                return 1


#定义截图函数
def ScreenShot(x1:int,y1:int,x2:int,y2:int,name:str):
    # im = Image.open('/usr/local/src/python_zhandan/Driver_%s.png'%(name))
    im = Image.open('/usr/local/src/qiandao_test/Driver_%s.png' % (name))
    crop = im.crop((x1,y1,x2,y2))
    #time.sleep(3)#延时2秒
    #print('test1')
    #im = ImageGrab.grab(bbox=(x1,y1,x2,y2))
    #print('test')
    #im.save('/usr/local/src/qiandao_test/test.jpg')
    # crop.save('/usr/local/src/python_zhandan/%s.png'%(name))
    crop.save('/usr/local/src/qiandao_test/%s.png' % (name))
    # crop1 = image.open('/usr/local/src/qiandao_test/%s.png'%(name))
    # im.show('001.png') test

# #定义一个清楚输入函数
def clean_and_input(element,text:str):
    element.send_keys(Keys.CONTROL,"a")
    element.send_keys(text)


# 图片识别部分
def CodeOcr(name:str)->str:
    ocr = ddddocr.DdddOcr()
    with open("%s.png"%(name), 'rb') as f:
        image = f.read()
    res = ocr.classification(image)
    return res
    # print(res) test
#获取时间戳，签名值
def getSignTimestamp(signature):
    timestamp = str(round(time.time() * 1000))
    secret = signature
    secret_enc = secret.encode('utf-8')
    string_to_sign = '{}\n{}'.format(timestamp, secret)
    string_to_sign_enc = string_to_sign.encode('utf-8')
    hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
    return (timestamp,sign)

#发送text信息到钉钉
def sendDing(url,text):
   headers = {
        'Content-Type': 'application/json',
    }
   data = {
       "at": {
           "atMobiles": [
               "13929508854"
           ],
           "atUserIds": [
               "mci1ljk"
           ],
           "isAtAll": False
       },
       'text': {
           'content': text,
       },
       'msgtype': 'text'
   }
   r = requests.post(url, headers=headers, data=json.dumps(data)).text
   json_r = json.loads(r)
   if json_r['errcode'] == 0:
       print("发送成功")
   else:
       print("发送失败")
       print(json_r['errcode'])
       print(json_r['errmsg'])


   #钉钉财务发送消息
def DingText_caiwu(text):
    signature = 'SECecd8ddb21e179b8a4898d75***'
    (times,signs) = getSignTimestamp(signature)
    webhook = 'https://oapi.dingtalk.com/robot/s********'
    urls = webhook + '&timestamp=' + times + '&sign=' + signs
    sendDing(urls,text)

#报错信息
def DingText(text):
    signature = 'secxxxxx'
    (times,signs) = getSignTimestamp(signature)
    webhook = 'https://oapi.dingtalk.com/robot/send?access_token=48ff****'
    urls = webhook + '&timestamp=' + times + '&sign=' + signs
    sendDing(urls,text)
 
#邮箱发送
def MailSend(to:str):
    user ='**********@163.com'#定义发件人邮箱
    pwd ='***********'#QQ邮箱POP3/SMTP的授权码/阿里云密码
    # current_date = datetime.datetime.strptime('%Y-%M')
    # to='caiwu@yegamer.com'
    # #dbpkpfeatlbvbcbf qq
    msg = MIMEMultipart()
    mail_msg = '<p>%s账单文件</p>'%(lastmoth)
    msg.attach(MIMEText(mail_msg, 'html', 'utf-8'))
    # att1 = MIMEText(open('1667102578286094-tiantianbaoliang-20230105164723-month_product_summary.csv', 'rb').read(),
    #                 'base64', 'utf-8')  # 添加附件，由于定义了中文编码，所以文件可以带中文

    # att1["Content-Type"] = 'application/octet-stream'  # 数据传输类型的定义
    # att1["Content-Disposition"] = 'attachment;filename="2023-01.csv"'  # 定义文件在邮件中显示的文件名和后缀名，名字不可为中文
    with open(r"/usr/local/src/zhandan_auto/%s.zip"%(lastmoth), 'rb') as f:
        # 这里附件的MIME和文件名，这里是xls类型
        mime = MIMEBase('zip', 'zip', filename='%s.zip'%(lastmoth))
        # 加上必要的头信息
        mime.add_header('Content-Disposition', 'attachment', filename=('gb2312', '', '%s.zip'%(lastmoth)))
        mime.add_header('Content-ID', '<0>')
        mime.add_header('X-Attachment-Id', '0')
        # 把附件的内容读进来
        mime.set_payload(f.read())
        # 用Base64编码
        encoders.encode_base64(mime)
        msg.attach(mime)  # 将附件添加到邮件内容当中
    # 配置调用邮件信息
    msg['Subject'] = '%s账单'%(lastmoth)  # 设置邮件主题
    msg['From'] = user  # 设置发件人
    msg['To'] = to  # 设置收件人

    # 执行命令
    s = smtplib.SMTP_SSL('smtp.qiye.aliyun.com',
                         465)  # 选择QQ邮箱服务，默认端口465（smtplib.SMTP()：构造函数，功能是与smtp服务器建立连接，连接成功后，就可以向服务器发送相关请求，比如登录，校验，发送，退出）
    s.login(user, pwd)  # 登录邮箱
    s.send_message(msg)  # 发送邮件
    s.quit()  # 退出邮箱服务

def LoginPass()->int:
    try:
        time.sleep(4)
        #driver.find_element(by=By.XPATH, value='/html/body/center/div[1]/div/div/div/div[2]/span')
        driver.find_element(by=By.XPATH,value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[2]/div[1]/div/div/span/button/span')
        return 1
    except:
        # #判断滑块模块
        return 0
        # source = driver.find_element(by=By.XPATH, value='/html/body/center/div[1]/div/div/div/div[2]/span')
        # ActionChains(driver).drag_and_drop_by_offset(source, 400, 0).perform()

def AccountPass()->int:
    try:
        time.sleep(4)
        driver.find_element(by=By.NAME, value="password")
        return 1
    except:
        return 0


 
if __name__ == '__main__':
    pdf = 'pdf'
    xls = 'xls'
    chrome_options = Options()
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    chrome_options.add_argument('--headless')
    chrome_options.add_argument("lang=zh_CN.UTF-8")
    chrome_options.add_argument('window-size=1920x1080')
    prefs = {'profile.default_content_settings.popups': 0,'download.default_directory':'/usr/local/src/zhandan'}
    chrome_options.add_experimental_option('prefs',prefs)
    for lines in open('account.txt', 'r'):
            if 'account:' in lines:
                account = lines.split(':')[1]
                passwd = lines.split(':')[2]
                line = account.split('@')[1]
                name = account.split('@')[0]
                # # url = "https://signin.aliyun.com/%s/login.htm?callback=https%3A%2F%2Fusercenter2.aliyun.com%2Ffinance%2Fexpense-report%2Fmonth%2Fdetail%3FconsumePeriod%3D2022-12%26account%3D1665468780605048#/main"%(line)
                num = line.split('.')[0]
                url = "https://signin.aliyun.com/%s/login.htm?callback=https%%3A%%2F%%2Fusercenter2.aliyun.com%%2Ffinance%%2Fexpense-report%%2Fmonth%%2Fdetail%%3FconsumePeriod%%3D%s%%26account%%3D%s#/main" % (
                    line,lastmoth,num)
                # print(line)
                # print(url+'正在打开网址登录')
                # print(num)
                #driver = webdriver.Chrome()
                #driver.maximize_window()
                driver = webdriver.Chrome(options = chrome_options)
                time.sleep(2)
                driver.get(url)
                #DingText('正在打开网站')
                # driver.get('https://signin.aliyun.com/1665468780605048.onaliyun.com/login.htm?callback=https%3A%2F%2Fusercenter2.aliyun.com%2Ffinance%2Fexport-record%3FdisableGoBack%3D1#/main')
                time.sleep(random.randint(8, 10))
                # print('开始登录%s'%(name))
                clean_and_input(driver.find_element(by=By.NAME, value="username"), account)
                #DingText('账号已输入')
                time.sleep(random.randint(1, 2))
                driver.find_element(by=By.XPATH,
                                    value="/html/body/div[2]/div[1]/div[2]/div/div/div[1]/div[2]/div/div/div/div/div/form/div[5]/button").click()
                #DingText('已点击登录按钮')
                time.sleep(random.randint(1,3))

                try:
                    driver.find_element(by=By.NAME, value="password").send_keys(passwd)
                except:
                    driver.get_screenshot_as_file('error_passwd.png')
                # DingText('已输入密码')
                time.sleep(random.randint(1, 2))
                #driver.find_element(by=By.XPATH,value="/html/body/div[2]/div[1]/div[2]/div/div/div[1]/div[2]/div/div/div/div/div/form/div[5]/button").click()
                time.sleep(random.randint(10, 12))
                #driver.get_screenshot_as_file('login.png')
                Login = LoginPass()
                if Login == 0:
                    for j in range(99):
                        DingText('%s登录出现滑块，正在重试' % (name))
                        driver.close()
                        time.sleep(4)
                        driver = webdriver.Chrome(chrome_options=chrome_options,
                                                  executable_path='/usr/bin/chromedriver')
                        driver.get(url)
                        time.sleep(random.randint(1,3))
                        # v.press_keysym(65421)  # Enter
                        # v.release_keysym(65421)
                        # ui.keyDown('Enter')
                        # ui.keyUp('Enter')
                        # ActionChains(driver).send_keys(Keys.ENTER).perform()
                        # ActionChains(driver).key_down(Keys.ENTER).key_up(Keys.ENTER).perform()
                        # driver.get_screenshot_as_file('login_error.png')
                        print('开始登录%s'%(name))
                        print(j)
                        driver.get_screenshot_as_file('test.png')
                        time.sleep(random.randint(4,6))
                        clean_and_input(driver.find_element(by=By.NAME, value="username"), account)
                        # DingText('账号已输入')
                        time.sleep(random.randint(1, 2))
                        driver.find_element(by=By.XPATH,
                                            value="/html/body/div[2]/div[1]/div[2]/div/div/div[1]/div[2]/div/div/div/div/div/form/div[5]/button").click()
                        # DingText('已点击登录按钮')
                        # time.sleep(999)
                        time.sleep(random.randint(4, 6))
                        try:
                            driver.find_element(by=By.NAME, value="password").send_keys(passwd)
                        # DingText('已输入密码')
                        except:
                            driver.get_screenshot_as_file('error_login.png')
                        time.sleep(random.randint(1, 3))
                        # driver.get_screenshot_as_file('test.png')
                        # driver.find_element(by=By.XPATH,value="/html/body/div[2]/div[1]/div[2]/div/div/div[1]/div[2]/div/div/div/div/div/form/div[5]/button").click()
                        Login = LoginPass()
                        if Login == 1:
                            DingText('%s登录成功' % (name))
                            break
                        else:
                            continue
                else:
                    # driver.get_screenshot_as_file('login_succ.png')
                    DingText('%s登录成功' % (name))
                driver.get_screenshot_as_file('language.png')
                time.sleep(random.randint(10, 15))
                try:
                    driver.find_element(by=By.XPATH,
                                        value='/html/body/div[5]/div/div/div[1]/div[4]/div[2]/button/span').click()
                except:
                    DingText('无弹窗')
                time.sleep(2)
                try:
                    driver.find_element(by=By.XPATH,value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[2]/div[1]/div/div/span/button/span').click()
                except:
                    driver.get_screenshot_as_file('error.png')
                #DingText('导出PDF')
                time.sleep(random.randint(9,12))
                driver.get_screenshot_as_file('Driver_pdf.png')
                time.sleep(random.randint(7, 10))
                ScreenShot(775,665,875,695,pdf)
                #print('test')
                #874 695 右下角
                #776 655 左上角
                time.sleep(random.randint(3, 5))
                pdfcode = CodeOcr(pdf)
                driver.find_element(by=By.XPATH,
                                    value='/html/body/div[5]/div[2]/div[2]/form[3]/div/div[2]/span/input').send_keys(
                    pdfcode)
                time.sleep(1)
                driver.find_element(by=By.XPATH, value='/html/body/div[5]/div[2]/div[3]/button[1]/span').click()
                # driver.get("https://signin.aliyun.com/1665468780605048.onaliyun.com/login.htm?callback=https%3A%2F%2Fusercenter2.aliyun.com%2Ffinance%2Fexpense-report%2Fmonth%2Fdetail%3FconsumePeriod%3D2022-12%26account%3D1665468780605048#/main") 
                pdfcode = CodePass(pdf)
                if pdfcode == 0:
                    for i in range(99):
                        driver.find_element(by=By.XPATH,value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[2]/div[1]/div/div/span/button/span').click()
                        # DingText('导出PDF')
                        driver.get_screenshot_as_file('Driver_pdf.png')
                        time.sleep(random.randint(7, 10))
                        ScreenShot(775, 664, 875, 695, pdf)
                        # print('test')
                        # 874 695 右下角
                        # 776 655 左上角
                        time.sleep(random.randint(3, 5))
                        pdfcode = CodeOcr(pdf)
                        driver.find_element(by=By.XPATH,
                                            value='/html/body/div[5]/div[2]/div[2]/form[3]/div/div[2]/span/input').send_keys(
                            pdfcode)
                        time.sleep(1)
                        driver.find_element(by=By.XPATH, value='/html/body/div[5]/div[2]/div[3]/button[1]/span').click()
                        pdfcode = CodePass(pdf)
                        # print(pas)
                        if CodePass(pdf) == 1:
                            break
                        else:
                            continue
                else:
                    DingText('验证通过')
                
                time.sleep(random.randint(5, 8))
                driver.get(url)
                time.sleep(random.randint(5,8))
                try:
                    driver.find_element(by=By.XPATH,
                                        value='/html/body/div[5]/div/div/div[1]/div[4]/div[2]/button/span').click()
                except:
                    DingText('无弹窗xls')
                # driver.find_element(by=By.XPATH,value='/html/body/div[5]/div/div/div[1]/div[4]/div[2]/button/span').click()
                # time.sleep(2)
                driver.get_screenshot_as_file('398_error.png')
                driver.find_element(by=By.XPATH,value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[2]/div[3]/div[1]/div/span/span/span/a').click()
                time.sleep(random.randint(3, 5))
                driver.get_screenshot_as_file('Driver_xls.png')
                time.sleep(1)
                ScreenShot(826,566,925,597,xls)
                #826 566
                #925 597
                time.sleep(random.randint(3, 5))
                xlscode = CodeOcr(xls)
                driver.find_element(by=By.XPATH,
                                    value='/html/body/div[5]/div[2]/div[2]/form[2]/div/div[2]/span/input').send_keys(
                    xlscode)
                time.sleep(1)
                driver.find_element(by=By.XPATH, value='/html/body/div[5]/div[2]/div[3]/button[1]').click()
                xlscode = CodePass(xls)
                if xlscode == 0:
                    for i in range(99):
                        driver.find_element(by=By.XPATH,
                                            value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[2]/div[3]/div[1]/div/span/span/span/a').click()
                        time.sleep(random.randint(3, 5))
                        driver.get_screenshot_as_file('Driver_xls.png')
                        ScreenShot(825, 603, 925, 634, xls)
                        # 826 566
                        # 925 597
                        time.sleep(random.randint(3, 5))
                        xlscode = CodeOcr(xls)
                        driver.find_element(by=By.XPATH,
                                            value='/html/body/div[5]/div[2]/div[2]/form[2]/div/div[2]/span/input').send_keys(
                            xlscode)
                        time.sleep(1)
                        driver.find_element(by=By.XPATH, value='/html/body/div[5]/div[2]/div[3]/button[1]').click()
                        xlscode = CodePass(xls)
                        if CodePass(xls) == 1:
                            break
                        else:
                            continue
                else:
                    DingText('验证通过')
                time.sleep(60)
                driver.find_element(by=By.XPATH,
                                    value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[1]/span[3]/button/span').click()


                time.sleep(random.randint(4, 6))
                driver.find_element(by=By.XPATH,
                                    value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/div/table/tbody/tr[1]/td[5]/div/div/a').click()
                print('%s账单开始下载' % (name))
                time.sleep(2)
                driver.find_element(by=By.XPATH,
                                    value='/html/body/div[2]/div[2]/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/div/table/tbody/tr[2]/td[5]/div/div/a').click()
                print('%s下载完成,准备下一个账号' % (name))
                time.sleep(3)  # 暂停30s
                if num in '1642473472575922':
                    src_dir = '/usr/local/src/zhandan/'
                    os.makedirs(r'/usr/local/src/zhandan_auto/%s/***'%(lastmoth))
                    dst_dir = '/usr/local/src/zhandan_auto/%s/***/'%(lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1221467580418418':
                    src_dir = '/usr/local/src/zhandan/'
                    dst_dir = '/usr/local/src/zhandan_auto/%s/***/' % (lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1606298004083597':
                    src_dir = '/usr/local/src/zhandan/'
                    os.makedirs(r'/usr/local/src/zhandan_auto/%s/***/'%(lastmoth))
                    dst_dir = '/usr/local/src/zhandan_auto/%s/***/'%(lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1669294263163346':
                    src_dir = '/usr/local/src/zhandan/'
                    dst_dir = '/usr/local/src/zhandan_auto/%s/***/' % (lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1665468780605048':
                    src_dir = '/usr/local/src/zhandan/'
                    os.makedirs(r'/usr/local/src/zhandan_auto/%s/**/'%(lastmoth))
                    dst_dir = '/usr/local/src/zhandan_auto/%s/**/'%(lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1667102578286094':
                    src_dir = '/usr/local/src/zhandan/'
                    dst_dir = '/usr/local/src/zhandan_auto/%s/**/'%(lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1461044474459513':
                    src_dir = '/usr/local/src/zhandan/'
                    os.makedirs(r'/usr/local/src/zhandan_auto/%s/***' % (lastmoth))
                    dst_dir = '/usr/local/src/zhandan_auto/%s/***/'%(lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1207802471665227':
                    src_dir = '/usr/local/src/zhandan/'
                    os.makedirs(r'/usr/local/src/zhandan_auto/%s/***' % (lastmoth))
                    dst_dir = '/usr/local/src/zhandan_auto/%s/***/'%(lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                elif num in '1221423818185423':
                    src_dir = '/usr/local/src/zhandan/'
                    dst_dir = '/usr/local/src/zhandan_auto/%s/**/' % (lastmoth)  # 目的路径记得加斜杠
                    src_file_list = glob(src_dir + '*')  # glob获得路径下所有文件，可根据需要修改
                    for srcfile in src_file_list:
                        mymovefile(srcfile, dst_dir)  # 移动文件
                time.sleep(30)

TxZhandan()
zipDir('/usr/local/src/zhandan_auto/%s' % (lastmoth), '/usr/local/src/zhandan_auto/%s.zip' % (lastmoth))
DingText('压缩完毕')
time.sleep(5)
MailSend('******@163.com')
DingText('已发送指定邮箱')
DingText_caiwu('账单已经发送到邮箱了，请及时查看并下载！')



